use std::{
    env::var_os,
    error::Error,
    fs::File,
    io::{BufRead, BufReader, BufWriter, Write as _},
    path::PathBuf,
};

use brotli_decompressor::Decompressor;

// Use longer literals for better buffering
macro_rules! lit_lines {
    ($($str:literal)* $(,)?) => {{
        concat!($($str, "\n"),* ).as_bytes()
    }};
}

fn main() -> Result<(), Box<dyn Error>> {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=data/s2t");
    println!("cargo:rerun-if-changed=data/t2s");

    let s2t = BufReader::new(Decompressor::new(File::open("data/s2t").unwrap(), 4096));
    let t2s = BufReader::new(Decompressor::new(File::open("data/t2s").unwrap(), 4096));

    let dict_path = PathBuf::from(var_os("OUT_DIR").unwrap()).join("dict.rs");
    let mut dict_output = BufWriter::new(File::create(dict_path).unwrap());

    dict_output.write_all(lit_lines!(
        "// This file is auto-generated by build.rs"
        "mod dict {"
        "    /// A Chinese to Traditional Chinese dictionary"
        "    pub static S2T: &[(&'static str, &'static str)] = &["
    ))?;

    let mut s2t_max_len = 0;

    for ele in s2t.lines() {
        let line = ele?;
        let (word, trad) = line
            .split_once('\t')
            .ok_or_else(|| format!("invalid entry: {:?}", line))?;
        writeln!(dict_output, "        ({:?}, {:?}),", word, trad)?;
        s2t_max_len = s2t_max_len.max(word.len());
    }

    dict_output.write_all(lit_lines!(
        "    ];" // S2T
        ""
        "    /// A Chinese to Simplified Chinese dictionary"
        "    pub static T2S: &[(&'static str, &'static str)] = &["
    ))?;

    let mut t2s_max_len = 0;

    for ele in t2s.lines() {
        let line = ele?;
        let (word, simp) = line
            .split_once('\t')
            .ok_or_else(|| format!("invalid entry: {:?}", line))?;
        writeln!(dict_output, "        ({:?}, {:?}),", word, simp)?;
        t2s_max_len = t2s_max_len.max(word.len());
    }

    dict_output
        .write_all(lit_lines!(
            "    ];" // T2S
            "}" // mod dict
            ""
            "pub use dict::{S2T, T2S};"
        ))
        .unwrap();

    Ok(())
}
